package com.bbm.communitysystem.sha256;


import cn.hutool.crypto.digest.DigestAlgorithm;
import cn.hutool.crypto.digest.Digester;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

/**
 * @author xieling
 * @version 1.0
 */
@SpringBootTest
@Slf4j
@SuppressWarnings("all")
public class SHA256 {

    //加密
    @Test
    void digest() {
        String password = "123456";

        Digester digester = new Digester(DigestAlgorithm.SHA256);

        String encrypted = digester.digestHex(password);

        log.info("加密后的密码：{},长度：{}", encrypted,encrypted.length());

        //盐值
        String salt = RandomStringUtils.randomNumeric(16);
        String sha256Hex = digester.digestHex(password + salt);

        log.info("盐值：{},盐值长度：{}", salt,salt.length());
        log.info("拼接盐值加密后的密码：{},长度：{}", sha256Hex,sha256Hex.length());

        StringBuilder sb = new StringBuilder(80);

        // 将盐混到新生成的SHA-256码中，之所以这样做是为了后期解密，校验密码
        for (int i = 0; i < 16; i++) {
            sb.append(sha256Hex.charAt(i * 4));
            sb.append(salt.charAt(i));
            sb.append(sha256Hex.charAt(i * 4 + 1));
            sb.append(sha256Hex.charAt(i * 4 + 2));
            sb.append(sha256Hex.charAt(i * 4 + 3));
        }

        log.info("添加盐值后的密文：{}, 长度：{}", sb.toString(), sb.length());

        code(sb.toString());
    }

    //解密
     public static void code(String encrypted) { //encrypted 混入盐的SHA-256码

        //拼接盐值后 SHA256加密的密文
        StringBuilder digest = new StringBuilder(64);
        //盐值
        StringBuilder salt = new StringBuilder(16);

        //解密 从混入盐的SHA-256码中提取盐值和加盐后的SHA-256码
        for (int i = 0; i < 16; i++) {
            // 从混入盐的SHA-256码中提取 拼接盐值后SHA256加密的密文
            digest.append(encrypted.charAt(i * 5));
            digest.append(encrypted.charAt(i * 5 + 2));
            digest.append(encrypted.charAt(i * 5 + 3));
            digest.append(encrypted.charAt(i * 5 + 4));
            // 从混入盐的SHA-256码中提取盐值
            salt.append(encrypted.charAt(i * 5 + 1));
        }

        // 原盐值
        String beginSalt = salt.toString();

        // 原密文(拼接盐后的加密的密文)
        String beginDigest = digest.toString();

        // 原密码(从数据库中获得)
        String password = "123456";

        // 加密器
        Digester digester = new Digester(DigestAlgorithm.SHA256);

        log.info("原盐值：{}", beginSalt);
        log.info("加密后的密码：{}", beginDigest);

        // 用数据库中的 原密码拼接盐值，然后进行SHA256加密，得到密文，与数据 beginDigest 进行比较，如果相同则验证成功。
        boolean equals = digester.digestHex(password + beginSalt).equals(beginDigest);

        log.info("验证结果：{}", equals);

    }
}
